package com.yangfan.juc.utils;

import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 * @description:  Phaser 模拟一个 铁人三项的运动
 * @author: yangfan
 * @date: Created in 2020/3/31 0031 14:06
 * @modified By:
 *
 *
 * phaser.arrive() 可以让线程到达后，而不需要再去等待别的线程而阻塞，直接继续请进。  先跑步，跑完步 直接就去骑自行车 不需要等别人 也跑完
 * phaser.arriveAndAwaitAdvance() 到达后需要等待 后面人线程。阻塞    跑完步 等待后面 的人都跑完 在一起去骑自行车
 *
 *
 *
 */
public class PhaserExample {

    private static Phaser phaser = new Phaser(5);


    private static Random random = new Random(System.currentTimeMillis());


    /**
     * 模拟 铁人三项 先跑步 在骑车  在跳远
     * @param args
     */
    public static void main(String[] args) {

        for (int i=1; i<5; i++){
            new Athletes(phaser,i).start();
        }

        new InjuredAthletes(phaser,5).start();


    }

    /**
     * 受伤的运动员
     */
    static class InjuredAthletes extends Thread{

        private Phaser phaser;
        private Integer number;

        InjuredAthletes(Phaser phaser, Integer number) {
            this.phaser = phaser;
            this.number = number;
        }

        @Override
        public void run() {

            try {

                System.out.println("运动员" + number + "跑步开始");
                TimeUnit.SECONDS.sleep(random.nextInt(5));
                System.out.println("运动员" + number + "跑步结束");
                phaser.arriveAndAwaitAdvance();

                System.out.println("运动员" + number + "骑车开始");
                TimeUnit.SECONDS.sleep(random.nextInt(5));
                System.out.println("运动员" + number + "骑车结束");
                phaser.arriveAndAwaitAdvance();

                System.out.println("运动员" + number + "无法进行跳远了！我受伤了！即将退出比赛！其他人请继续！");
                phaser.arriveAndDeregister();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }


    /**
     * 运动员类
     */
    static class Athletes extends Thread{

        private Phaser phaser;

        private Integer number;

        Athletes(Phaser phaser, Integer number) {
            this.phaser = phaser;
            this.number = number;
        }

        @Override
        public void run() {

            sport(number, phaser, "跑步开始", "跑步结束");

            sport(number, phaser, "骑车开始", "骑车结束");

            sport(number, phaser, "跳远开始", "跳远结束");

        }


    }


    private static void sport(Integer number, Phaser phaser, String str1, String str2) {
        try {
            System.out.println("运动员" + number + str1);
            TimeUnit.SECONDS.sleep(random.nextInt(5));
            System.out.println("运动员" + number + str2);
            phaser.arriveAndAwaitAdvance();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}
